﻿using System;
using System.Net;
using System.Text.RegularExpressions;
using OpenWaves.Caching;

namespace OpenWaves.Video.YouTube
{
    public class YoutubeApi : VideoApi, IVideoWebsiteApi
    {
        public static readonly string YoutubeEmbedUrlFormat = "http://www.youtube.com/embed/{0}?enablejsapi=1";
        public static readonly string YoutubeApiUrlFormat = "http://gdata.youtube.com/feeds/api/videos/{0}?v=2";

        public static readonly Regex YoutubeVideoRegex =
            new Regex(@"youtu(?:\.be|be\.com)/(?:.*v(?:/|=)|(?:.*/)?)([a-zA-Z0-9-_]+)");

        private readonly IConcurrentCache<IVideo> videoCache;

        private Match match;
        private Func<Url, string> webClient;

        public YoutubeApi()
            : this(new ConcurrentCache<IVideo>(Cache.Null<IVideo>()))
        {
        }

        public YoutubeApi(IConcurrentCache<IVideo> videoCache)
            : this(videoCache, GetDefaultWebClient())
        {
        }


        public YoutubeApi(IConcurrentCache<IVideo> videoCache, Func<Url, string> webClient)
        {
            this.videoCache = videoCache;
            this.webClient = webClient;
        }


        public bool IsSupported(string url, out string videoId)
        {
            match = YoutubeVideoRegex.Match(url);
            videoId = match.Groups[1].Value;
            return match.Success;
        }


        public IVideo GetVideo(string url)
        {
            string videoId;
            var isSupported = IsSupported(url, out videoId);

            if(!isSupported)
            {
                return null;
            }

            try
            {
                return videoCache.GetOrCreate(url, () => 
                {
                    var apiUrl = string.Format(YoutubeApiUrlFormat, videoId);
                    var xmlString = this.webClient(Url.Parse(apiUrl));
                    var item = RestDeserializer.Deserialize<YouTubeVideo>(xmlString);
                    return CacheEntry.FromValue((IVideo)item, TimeSpan.FromHours(1));
                });
            }
            catch (WebException webException)
            {
                return null;
            }

            
        }

        public bool IsSupported(string url)
        {
            string videoId;
            return this.IsSupported(url, out videoId);
        }
    }
}